home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Other Stuff / Other Stuff ’97 / PowerOS Development / booter / elf_makeimage.c < prev    next >
Text File  |  1997-06-26  |  4KB  |  155 lines

  1. /*
  2.     elf_makeimage.c
  3.     copyright 1996-1997 by Ben Martz
  4.     all rights reserved world wide
  5.  
  6.     ANY AND ALL MODIFICATIONS TO THIS SOURCE MUST CREDIT THE ORIGINAL
  7.     AUTHOR, BEN MARTZ (benmartz@ic.net), AND MUST BE GIVEN TO THE AUTHOR
  8.     FOR INTEGRATION INTO THE MAIN PowerOS SOURCE TREE. THANK YOU FOR YOUR
  9.     COOPERATION!
  10.  
  11.     This program takes a PowerPC ELF binary and converts it to an image
  12.     that can be loaded into memory and executed directly.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <time.h>
  19.  
  20. #include "elf_format.h"
  21.  
  22. long elf_makeimage(char *fname, char **kptr);
  23.  
  24. long elf_makeimage(char *fname, char **kptr) {
  25.     char        *kerneldata;
  26.     char        filename[256];
  27.     OSErr        err;
  28.     FSSpec        spec;
  29.     FInfo        fndrInfo;
  30.     short        file,count;
  31.     long        filelen, len, offset, i;
  32.     char        *filedata;
  33.     Elf32_Hdr    *header;
  34.     Elf32_Shdr    *sheader;
  35.     UInt32        text_start = 0;
  36.     UInt32        last_start = 0,last_offset,last_size;
  37.     UInt32        sect_start = 0,sect_offset,sect_size;
  38.     long        totallen = 0;
  39.  
  40.     /* convert c to p str */
  41.     strcpy(filename+1,fname);
  42.     filename[0] = strlen(filename+1);
  43.     
  44.     /* open and read in the binary file */
  45.     err = FSMakeFSSpec(0,0,(unsigned char *)filename,&spec);
  46.     if(err != noErr) return -1;
  47.     
  48.     /* fix creator and type */
  49.     err = FSpGetFInfo(&spec,&fndrInfo);
  50.     if(err == noErr) {
  51.         fndrInfo.fdType = 'elf ';
  52.         fndrInfo.fdCreator = 'pos ';
  53.         FSpSetFInfo(&spec,&fndrInfo);
  54.     }
  55.     
  56.     err = FSpOpenDF(&spec,fsRdPerm,&file);
  57.     if(err != noErr) return -1;
  58.     
  59.     err = GetEOF(file,&filelen);
  60.     if(err != noErr) return -1;
  61.     
  62.     filedata = NewPtrClear(filelen);
  63.     if(!filedata) return -1;
  64.     
  65.     len = filelen;
  66.     err = FSRead(file,&len,filedata);
  67.     if(err != noErr) return -1;
  68.     if(len != filelen) return -1;
  69.     
  70.     FSClose(file);
  71.     
  72.     header = (Elf32_Hdr *) filedata;
  73.         
  74.     /* make sure that this is a binary file that we can handle! */
  75.     if((header->ei_magic[1] != 'E') || (header->ei_magic[2] != 'L') || (header->ei_magic[3] != 'F')) return -1;
  76.     
  77.     if(header->ei_version != 1) return -1;
  78.     
  79.     if(header->e_machine != EM_PPC601) return -1;
  80.     
  81.     if(!header->e_shnum) return -1;
  82.         
  83.     /* find the program sections */
  84.     /* read through once to find the memory size to allocate */
  85.     last_start = last_offset = last_size = 0L;
  86.     for(count = 0; count < header->e_shnum; count++) {
  87.         sect_start = sect_offset = sect_size = 0L;
  88.         offset = header->e_shoff + (header->e_shentsize * count);
  89.         if(offset < (long)(filedata + filelen - sizeof(Elf32_Shdr))) {
  90.             sheader = (Elf32_Shdr *) (filedata + offset);
  91.             if(sheader->sh_type == SHT_PROGBITS) {
  92.                 sect_start = sheader->sh_addr;
  93.                 sect_offset = sheader->sh_offset;
  94.                 sect_size = sheader->sh_size;
  95.                 
  96.                 if(sect_start > last_start + last_size) {
  97.                     /* pad with zero */
  98.                     len = sect_start - (last_start + last_size);
  99.                     totallen += len;
  100.                 }
  101.                 
  102.                 if(sheader->sh_flags == SECT_TEXT) text_start = sect_start;
  103.                 
  104.                 len = sect_size;
  105.                 totallen += len;
  106.                 
  107.                 last_start = sect_start;
  108.                 last_offset = sect_offset;
  109.                 last_size = sect_size;
  110.             }
  111.         }
  112.     }
  113.     
  114.     kerneldata = NewPtrClear(totallen);
  115.     if(!kerneldata) return -1;
  116.     
  117.     *kptr = kerneldata;
  118.     
  119.     /* extract the sections now */
  120.     totallen = 0;
  121.     last_start = last_offset = last_size = 0L;
  122.     for(count = 0; count < header->e_shnum; count++) {
  123.         sect_start = sect_offset = sect_size = 0L;
  124.         offset = header->e_shoff + (header->e_shentsize * count);
  125.         if(offset < (long)(filedata + filelen - sizeof(Elf32_Shdr))) {
  126.             sheader = (Elf32_Shdr *) (filedata + offset);
  127.             if(sheader->sh_type == SHT_PROGBITS) {
  128.                 sect_start = sheader->sh_addr;
  129.                 sect_offset = sheader->sh_offset;
  130.                 sect_size = sheader->sh_size;
  131.                 
  132.                 if(sect_start > last_start + last_size) {
  133.                     /* pad with zero */
  134.                     len = sect_start - (last_start + last_size);
  135.                     totallen += len;
  136.                     while(len--) *((char *)(kerneldata++)) = '\0';
  137.                 }
  138.                 
  139.                 if(sheader->sh_flags == SECT_TEXT) text_start = sect_start;
  140.                 
  141.                 len = sect_size;
  142.                 totallen += len;
  143.                 for(i = 0; i < len; i++) {
  144.                     *((char *)(kerneldata++)) = *((char *) filedata+sect_offset+i);
  145.                 }
  146.                 
  147.                 last_start = sect_start;
  148.                 last_offset = sect_offset;
  149.                 last_size = sect_size;
  150.             }
  151.         }
  152.     }
  153.     
  154.     return totallen;
  155. } /* end of main */